#==============================================================================
# -- Definitions

ifndef GEL_DIR
GEL_DIR=ext/GEL
endif

# We require GCC version 9.1 or later due to the "filesystem" library
GCC_REQ_VER := 90100
GCC_VER_CHECK := $(shell expr `gcc -dumpfullversion -dumpversion | sed -e 's/\.\([0-9][0-9]\)/\1/g' -e 's/\.\([0-9]\)/0\1/g' -e 's/^[0-9]\{3,4\}$$/&00/'` \>= $(GCC_REQ_VER))
ifeq "$(GCC_VER_CHECK)" "0"
$(error We require GCC version 9.1 or later, however $(shell gcc -dumpfullversion -dumpversion) found.)
endif

# - Compilers. Check if MPI is available.
MPICXX = $(shell which mpicxx)
ifneq ($(MPICXX),)
	CXX = mpicxx
	USE_MPI = 1
else
	CXX = g++
	USE_MPI = 0
endif

# - C++ Flags
OPTIM   =-O3
WARN    =-Wall -Wno-unknown-pragmas
INCL    =-std=c++17 -I$(GEL_DIR)/src -Iext/ -MMD
CHIP    =
PARA    =-fopenmp -DUSE_MPI=$(USE_MPI)
LDFLAGS =-L$(GEL_DIR)/lib
LDLIBS  =-lGEL -fopenmp

CXXFLAGS  = $(OPTIM) $(WARN) $(INCL) $(CHIP) $(PARA)

# -- End of Definitions
#==============================================================================
# -- File definitions and macros

# - Directories
SRCDIR   = src
OBJDIR   = obj

# -- End of File definitions
#==============================================================================
# -- Variable setup before compilation         (Avoid changes beyond this point)
VPATH    = $(shell find $(SRCDIR) -type d)
INCLUDES = $(addprefix -I, $(SRCDIR))

# - All C++ files in src main dir is a main function
EXEC     = $(addsuffix .exe, $(notdir $(basename $(shell ls $(SRCDIR)/*.cpp) )))
SOURCES  = $(shell find $(SRCDIR)/ -name *.cpp)

TMP      = $(filter-out $(addprefix $(SRCDIR)/, $(EXEC:.exe=.cpp)), $(SOURCES))
OBJECTS  = $(patsubst $(SRCDIR)/%, $(OBJDIR)/%, $(TMP:.cpp=.o))

# - Setup the directory list, compilation mimick original structure
DIR = $(OBJDIR) $(patsubst $(SRCDIR)/%, $(OBJDIR)/%, $(shell find $(SRCDIR) -type d))

# - Colour settings
GREEN=\e[0;32;01m
RED=\e[0;31;01m
YELLOW=\e[0;33;01m
WHITE=\e[0m

#==============================================================================
# -- Compilations and rules
.PHONY: all clean realclean
.SILENT: run all

all: $(EXEC)
	@printf "\n$(GREEN)make$(WHITE): Complete.\n"

# - Linking to binary
$(EXEC): $(OBJECTS)
	@printf "$(GREEN)make$(WHITE): link $@\n"
	@$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@

# - CPP Files
$(OBJDIR)/%.o: %.cpp | $(OBJDIR)
	@mkdir -p $(DIR)
	@printf "$(GREEN)make$(WHITE): $(CXX) $<\n"
	@$(CXX) -o $@ -c $< $(CXXFLAGS) $(INCLUDES)

# - Main Files
$(EXEC): %.exe: $(OBJDIR)/%.o

# - Header Files
-include $(OBJECTS:%.o=%.d)

# -- End of compilations
#==============================================================================
# -- Utility commands

# - Folder creation
$(OBJDIR):
	@mkdir -p $(DIR)

# - Cleanup commands
clean_tmp:
	@rm -fr tmp
clean:
	@rm -fr $(OBJDIR)
realclean: clean
	@rm -f $(EXEC)

# -- End of utility commands
#==============================================================================
